package service

import (
	"errors"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"seat-service/initialization"
	"seat-service/model"
	"seat-service/model/dto"
	"strconv"
)

type CasbinService struct {
}

const (
	tableCasbin = "casbin_rule"
)

func (c *CasbinService) CreateUser(userCode int, role string, ordered int, status int) error {
	//添加之前首先判断角色是否码是否存在
	var userCasbin model.CasbinRuleExtended
	var checkCasbin model.CasbinRuleExtended
	err := initialization.DB.Where("v0 = ?", userCode).Find(&checkCasbin).Error
	if checkCasbin.ID != 0 {
		//说明角色码已经存在
		return errors.New("RoleISExist")
	}
	userCasbin.Ptype = "g"                 //角色
	userCasbin.V0 = strconv.Itoa(userCode) //角色码
	userCasbin.V1 = role                   //角色名称
	userCasbin.Ordered = ordered           //排序
	userCasbin.Status = status             //状态
	err = initialization.DB.Create(&userCasbin).Error
	return err
}

func (c *CasbinService) GetRoleByUserCode(code int) (casbin []model.CasbinRuleExtended, err error) {
	err = initialization.DB.Where("ptype = 'g' and v0 = ?", code).Find(&casbin).Error
	return
}

func (c *CasbinService) SelectRoles(condition dto.PageParam) (err error, rolesInformation []model.CasbinRuleExtended, total int64) {
	db := initialization.DB.Table(tableCasbin).Where("ptype = 'g' and v1 like ?", "%"+condition.Data.(string)+"%")
	offset := (condition.PageNo - 1) * condition.PageSize
	err = db.Offset(offset).Limit(condition.PageSize).Order("ordered DESC").Find(&rolesInformation).Count(&total).Error
	return
}

func (c *CasbinService) SelectRoleById(id int) (role model.CasbinRuleExtended, err error) {
	err = initialization.DB.Table(tableCasbin).Where("id = ? and ptype = 'g'", id).Find(&role).Error
	return
}

func (c *CasbinService) ChangeRoleById(newRoleInformation dto.ChangeRole) (role model.CasbinRuleExtended, err error) {
	newRole := model.CasbinRuleExtended{
		CasbinRule: gormadapter.CasbinRule{
			Ptype: "g",                                       //角色
			V0:    strconv.Itoa(newRoleInformation.RoleCode), //角色编码
			V1:    newRoleInformation.Role,
		},
		Ordered: newRoleInformation.Ordered,
		Status:  newRoleInformation.Status,
	}
	if newRoleInformation.Ordered == 0 {
		err = initialization.DB.Model(&model.CasbinRuleExtended{}).Where("id = ? and ptype='g'", newRoleInformation.ID).Updates(map[string]interface{}{
			"ordered": newRoleInformation.Ordered,
		}).Error
	}
	if newRoleInformation.Status == 0 {
		err = initialization.DB.Model(&model.CasbinRuleExtended{}).Where("id = ? and ptype='g'", newRoleInformation.ID).Updates(map[string]interface{}{
			"status": newRoleInformation.Status,
		}).Error
	}
	err = initialization.DB.Where("id = ? and ptype='g'", newRoleInformation.ID).Updates(&newRole).Error
	role, err = c.SelectRoleById(newRoleInformation.ID)
	return
}

func (c *CasbinService) DeleteRoleByIds(ids []int) (err error) {
	err = initialization.DB.Where("id in (?) and ptype = 'g'", ids).Delete(&model.CasbinRuleExtended{}).Error
	return
}

func (c *CasbinService) Allocate(ruleIds dto.RuleID) (err error) {
	//判断新增的要新增的权限是否存在
	tx := initialization.DB.Begin()
	for _, saveId := range ruleIds.SaveIds {
		//查询新增的权限是否存在 , 存在即可忽略
		var ruleId model.CasbinRuleExtended
		tx.Where("v0 = ? and v1 = ?", ruleIds.Role, saveId).Find(&ruleId)
		if ruleId.ID == 0 {
			ruleId.Ptype = "p"
			ruleId.V0 = ruleIds.Role
			ruleId.V1 = strconv.Itoa(saveId)
			//插入数据
			if err = tx.Create(&ruleId).Error; err != nil {
				tx.Rollback()
				return err
			}
		}
	}
	if err = tx.Where("ptype = 'p' and  v1 in (?)", ruleIds.DeleteIds).Delete(model.CasbinRuleExtended{}).Error; err != nil {
		tx.Rollback()
		return
	}
	//提交事务
	tx.Commit()
	return
}

func (c *CasbinService) GetRoleName(roleId int) (roleName []model.CasbinRuleExtended, err error) {
	//根据角色id , 查询角色名称
	var casbin []model.CasbinRuleExtended
	err = initialization.DB.Where("ptype = 'g' and v0 = ?", roleId).Find(&casbin).Error
	return casbin, err
}

func (c *CasbinService) CheckControl(roleName string, menuId int) (isControl bool, err error) {
	//根据角色id , 查询角色名称
	var casbin model.CasbinRuleExtended
	err = initialization.DB.Where("ptype = 'p' and v0 = ? and v1 = ?", roleName, menuId).Find(&casbin).Error
	if casbin.ID == 0 {
		return false, err
	}
	return true, err
}
